package com.leyou.sms.utils;

import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.gitee.yongzhuzl.commonutil.util.empty.EmptyUtil;
import com.gitee.yongzhuzl.commonutil.util.equals.EqualsUtil;
import com.leyou.sms.config.SmsAlyProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

/**
 * description: 发送阿里云短信工具类
 * @author 朱正磊
 * @date 2021-04-15 17:25:42
 */
@Slf4j
@Component
public class SmsAlyUtils {

    @Resource
    private SmsAlyProperties smsAlyProperties;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 产品名称:云通信短信API产品,开发者无需替换
     */
    private static final String PRODUCT = "Dysmsapi";

    /**
     * 产品域名,开发者无需替换
     */
    private static final String DOMAIN = "dysmsapi.aliyuncs.com";

    /**
     * 短信手机号前缀
     */
    private static final String KEY_PREFIX = "sms:phone:";

    /**
     * 连续给同一个人发送同一种短信最短时间间隔（ms）
     */
    private static final Long SMS_MIN_INTERVAL_IN_MILLIS = 60 * 1000L;

    /**
     * description: 发送阿里云短信
     * @author 朱正磊
     * @date 2021-04-15 17:39:35
     * @param phoneNumber 手机号码
     * @param signName 签名
     * @param templateCode 模板
     * @param templateParam 模板参数
     */
    public void sendSmsAly(String phoneNumber, String signName, String templateCode, String templateParam) {
        String key = KEY_PREFIX + phoneNumber;
        // 根据手机号码进行限流
        String lastTime = stringRedisTemplate.opsForValue().get(key);
        if (lastTime != null && EmptyUtil.isNotEmpty(lastTime)) {
            Long last = Long.valueOf(lastTime);
            if (System.currentTimeMillis() - last < SMS_MIN_INTERVAL_IN_MILLIS) {
                // 如果上次距本次发送短信不足1分钟，则不允许发送本次短信
                log.info("【短信微服务】发送阿里云短信频率过高，被阻止，手机号码：{}", phoneNumber);
                return;
            }
        }
        try {
            // 可自助调整超时时间
            System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
            System.setProperty("sun.net.client.defaultReadTimeout", "10000");

            // 初始化acsClient,暂不支持region化
            IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou",
                    smsAlyProperties.getAccessKeyId(), smsAlyProperties.getAccessKeySecret());
            DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", PRODUCT, DOMAIN);
            IAcsClient acsClient = new DefaultAcsClient(profile);

            // 组装请求对象-具体描述见控制台-文档部分内容
            SendSmsRequest request = new SendSmsRequest();
            request.setMethod(MethodType.POST);
            // 必填:待发送手机号
            request.setPhoneNumbers(phoneNumber);
            // 必填:短信签名-可在短信控制台中找到
            request.setSignName(signName);
            // 必填:短信模板-可在短信控制台中找到
            request.setTemplateCode(templateCode);
            // 可选:模板中的变量替换JSON串
            request.setTemplateParam(templateParam);

            // hint 此处可能会抛出异常，注意catch
            SendSmsResponse response = acsClient.getAcsResponse(request);
            if (EqualsUtil.isNotEquals(response.getCode(), "OK")) {
                log.info("【短信微服务】发送阿里云短信失败，手机号码：{}，原因：{}", phoneNumber, response.getMessage());
            }

            // 记录发送短信日志
            log.info("【短信微服务】成功发送阿里云短信验证码，手机号码：{}", phoneNumber);

            // 发送验证码短信成功之后，写入redis，key为手机号码，value为当前时间
            // 指定生存时间为1分钟
            String value = String.valueOf(System.currentTimeMillis());
            stringRedisTemplate.opsForValue().set(key, value, 1, TimeUnit.MINUTES);
        } catch (Exception e) {
            log.error("【短信微服务】发送阿里云短信异常，手机号码：{}", phoneNumber, e);
        }
    }

}
